﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using StreetPacMan.Server.Facade;

namespace StreetPacMan.Server
{
    public class TwoGeos
    {
        public Geo First { get; private set; }
        public Geo Second { get; private  set; }

        [DebuggerNonUserCode]
        public TwoGeos(Geo first, Geo second)
        {
            First = first;
            Second = second;
        }

        public double DistanceInMeters
        {
            get { return GetDistance(First.Lat, First.Lon, Second.Lat, Second.Lon); }
        }

        public Geo GetPointAtPercentPartOfTheWay(double percent)
        {
            var lat = (Second.Lat) + ((First.Lat - Second.Lat) * percent);
            var lon = (Second.Lon) + ((First.Lon - Second.Lon) * percent);
            return new Geo(lat, lon);
        }

        static int earthRadius = 6378137; // meters
        static double degreesToRadians = Math.PI / 180;
        public const double OneMeterEstimate = 0.00000898472597;
        public static double GetDistance(double lat1, double lon1, double lat2, double lon2)
        {
            var dLat = (lat2 - lat1) * degreesToRadians;
            var dLon = (lon2 - lon1) * degreesToRadians;
            var a = Math.Sin(dLat / 2.0) * Math.Sin(dLat / 2.0) +
                    Math.Cos(lat1 * degreesToRadians) * Math.Cos(lat2 * degreesToRadians) *
                    Math.Sin(dLon / 2.0) * Math.Sin(dLon / 2.0);
            var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
            var d = earthRadius * c;
            return d;
        }

        public override string ToString()
        {
            return string.Format("{0} to {1}", First,Second);
        }
        public IEnumerable<Geo> GetPointsOnVectorEveryXMeters(int everyXMeters)
        {
            var distance = DistanceInMeters;
            var numberOfPoints = (distance - everyXMeters) / everyXMeters;
            double percent = 0;
            while (percent < 1)
            {
                var pointGeo = GetPointAtPercentPartOfTheWay(percent);
                yield return new Geo(pointGeo.Lat, pointGeo.Lon);
                percent += 1.0 / numberOfPoints;
            }

            var lastPointGeo = GetPointAtPercentPartOfTheWay(1);
            yield return new Geo(lastPointGeo.Lat, lastPointGeo.Lon);
        }
    }
}